#include "StdAfx.h"

ConfigFile ConfigFile::cfgMain(".\\Config\\Main.txt");
bool ConfigFile::mConfigsLoaded = false;

ConfigFile::ConfigFile(const std::string& fileName) : mFileName(fileName)
{
}

bool ConfigFile::Parse(std::string& error)
{
	std::fstream inStrm;
	inStrm.open(mFileName.c_str(), std::ios::in);
	if(!inStrm.is_open())
	{
		error = "File not found";
		return false;
	}

	ui32 lineNum = 0;
	std::string curLine;
	while(std::getline(inStrm, curLine))
	{
		++lineNum;

		while(curLine.length() > 0 && (curLine[0] == ' ' || curLine[0] == '\t'))
			curLine.erase(0, 1);

		if(curLine.length() == 0)
			continue;

		if(curLine[0] == '#')
			continue;

		if(curLine.find('=') == std::string::npos)
		{
			std::stringstream strm;
			strm << "Error in line '" << lineNum << "': Lines does not contain any '='.";
			error = strm.str();
			return false;
		}

		std::string::size_type posEq = curLine.find('=');
		std::string descriptor = curLine.substr(0, posEq);
		std::string::size_type trRight = descriptor.find_last_not_of(" \t");
		descriptor = descriptor.substr(0, trRight + 1);
		
		std::string value = curLine.substr(posEq + 1);
		if(value != "")
		{
			std::string::size_type trLeft = value.find_first_not_of(" \t");
			if(trLeft == std::string::npos)
				value == "";
			else
			{
				value = value.substr(trLeft);
				while(value.length() > 0 && (value[value.length() - 1] == ' ' || value[value.length() - 1] == '\t'))
					value.erase(value.length() - 1, 1);
			}
		}

		std::transform(descriptor.begin(), descriptor.end(), descriptor.begin(), tolower);
		mConfigValues.insert(std::make_pair(descriptor, value));
	}

	return true;
}

bool ConfigFile::ContainsKey(const std::string& key)
{
	std::string lower(key.length(), '\0');
	std::transform(key.begin(), key.end(), lower.begin(), tolower);

	return mConfigValues.find(lower) != mConfigValues.end();
}

std::string ConfigFile::GetValue(const std::string& key)
{
	std::string lower(key.length(), '\0');
	std::transform(key.begin(), key.end(), lower.begin(), tolower);

	if(!ContainsKey(key))
		throw std::out_of_range("Key not found in config file!");

	return mConfigValues[lower];
}

bool ConfigFile::LoadConfigs()
{
	if(mConfigsLoaded)
		return true;

	Log::Print("Loading configs...\n");
	std::string error;
	if(!cfgMain.Parse(error))
	{
		StartupException e;
		std::stringstream strm;
		strm << "Error parsing config file Main.txt: " << std::endl;
		strm << error;
		e.szBody = strm.str();
		e.szTitle = "Config Error";
		throw e;
	}

	mConfigsLoaded = true;
	return true;
}